package com.song.promoter.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.dom4j.Element;
import org.dom4j.Node;

import com.song.promoter.core.util.Cons;
@SuppressWarnings("unchecked")
public class WebInfo {
	private Log log = LogFactory.getLog(WebInfo.class);
	private String webName;
	private HttpClient httpClient = null;
	private Element webElement;
	private LinkedHashMap<String, String> keyMap = new LinkedHashMap<String, String>();
	private int keyNum = 0;
	private HashMap<String, String[]> respMap = new HashMap<String, String[]>();
	private boolean isLoginSuccess = false;
	private boolean isSkip = false;
	
	public WebInfo(Element webElement){
		if(null == webElement){
			log.error("初始化" + webName + "时出错...");
			return ;
		}
		this.webElement = webElement;
		webName = webElement.attributeValue("name");
		Node skipNode = webElement.selectSingleNode("skip");
		if(null != skipNode){
			String skip = skipNode.getText();
			if(StringUtils.isNotBlank(skip)){
				if(Cons.ISSKIP_TRUE.equals(skip.trim())){
					isSkip = true;
				}else{
					isSkip = false;
				}
			}
		}
		try {
			parseKey();
		} catch (Exception e) {
			log.error("登录" + webName + "时出错...", e);
		}
	}
	/**
	 * 解析用户名密码.
	 * @throws Exception
	 */
	private void parseKey() throws Exception{
		if(null == webElement){
			throw new Exception("登录" + webName + "时出错,reqNode为空.");
		}
		List<Node> keysNodes = webElement.selectNodes("login/req/keys/key");
		if(keysNodes != null && keysNodes.size()>0){
			for (Node node : keysNodes) {
				Element keyElement = (Element)node;
				String username = keyElement.attributeValue("username");
				String password = keyElement.attributeValue("password");
				if(StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)){
					keyMap.put(username, password);
				}
			}
		}
	}
	/**
	 * 登录
	 * @throws Exception
	 */
	public void login() throws Exception{
		if(null == webElement){
			throw new Exception("登录" + webName + "时出错,httpClient或者reqNode为空.");
		}
		httpClient = new DefaultHttpClient(new PoolingClientConnectionManager());
		List<Node> reqList = webElement.selectNodes("login/req");
		String respStr = null;
		if(reqList != null && reqList.size()>0){
			for (Node reqNode : reqList) {
				try {
					respStr = executeReq((Element)reqNode);
				} catch (Exception e) {
					log.error("登录时出错...", e);
					break;
				}
			}
		}
		//检验是否登录成功.
		if(StringUtils.isNotBlank(respStr)){
			isLoginSuccess(respStr);
		}else{
			log.info("返回结果为空,无法确定是否登录成功.");
		}
	}
	/**
	 * 执行请求
	 * @param reqElement
	 * @throws Exception
	 */
	private String executeReq(Element reqElement) throws Exception{
		String method = reqElement.attributeValue("method");
		String url = reqElement.attributeValue("url");
		if(StringUtils.isBlank(url)){
			log.error("登录时"+ webName +",请求url出错..");
			return null;
		}
		if(url.contains("${") && url.contains("}")){
			int num = 0;
			if(url.contains("${") && url.contains("}[") && url.contains("]")){
				num = Integer.parseInt(StringUtils.substringBetween(url, "[", "]"));
			}
			String[] strArray = respMap.get(StringUtils.substringBetween(url, "${", "}"));
			if(null != strArray && strArray.length > num){
				url = strArray[num];
			}else{
				log.error("登录时"+ webName +",获取中间数据,出错.");
			}
		}
		HttpRequestBase httpMethod = null;
		if(StringUtils.isBlank(method)||StringUtils.isBlank(url)){
			throw new Exception("登录" + webName + "时出错,method或者url为空.");
		}
		//生成method方法
		if(Cons.METHOD_POST.equals(method.trim())){
			httpMethod = new HttpPost(url);
			//设置pairs
			List<NameValuePair> pairs = new ArrayList<NameValuePair>(); 
			List<Node> pairList = reqElement.selectNodes("pairs/pair");
			if(null != pairList && pairList.size()>0){
				for (Node pairNode : pairList) {
					Element pairElement = (Element)pairNode;
					String pairName = pairElement.attributeValue("name");
					String pairValue = null;
					String alias = pairElement.attributeValue("alias");
					if(StringUtils.isBlank(alias)){
						pairValue = pairElement.attributeValue("value");
					}else{
						String username = this.getUserName();
						if(Cons.ALIAS_USERNAME.equals(alias.trim())){
							pairValue = username;
						}else if(Cons.ALIAS_PASSWORD.equals(alias.trim())){
							pairValue = keyMap.get(username);
						}else{
							throw new Exception("登录时用户名密码的别名错误...");
						}
					}
					if(StringUtils.isNotBlank(pairName) && null != pairValue){
						pairs.add(new BasicNameValuePair(pairName, pairValue));
					}
				}
			}
			((HttpPost)httpMethod).setEntity(new UrlEncodedFormEntity(pairs, Consts.UTF_8));
		}else if(Cons.METHOD_GET.equals(method.trim())){
			httpMethod = new HttpGet(url);
		}else{
			throw new Exception("登录" + webName + "时出错,method错误.");
		}
		//设置head
		List<Node> headList = reqElement.selectNodes("heads/head");
		if(null != headList && headList.size()>0){
			for (Node headNode : headList) {
				Element headElement = (Element)headNode;
				String headName = headElement.attributeValue("name");
				String headValue = headElement.attributeValue("value");
				if(StringUtils.isNotBlank(headName) && StringUtils.isNotBlank(headValue)){
					httpMethod.addHeader(headName, headValue);
				}
			}
		}
		log.info("请求url:" + url);
		HttpResponse response = httpClient.execute(httpMethod);
		String respString = EntityUtils.toString(response.getEntity());
		List<Node> resqNodeList = reqElement.selectNodes("resps/resp");
		if(resqNodeList != null && resqNodeList.size()>0){
			for (Node node : resqNodeList) {
				Element resqElement = (Element)node;
				String context = resqElement.attributeValue("context");
				String key = resqElement.attributeValue("key");
				if(StringUtils.isNotBlank(context) 
						&& StringUtils.isNotBlank(key)){
					if(Cons.RESP_CONTEXT_HEAD.equals(context)){
						String value = resqElement.attributeValue("value");
						if(StringUtils.isNotBlank(value)){
							Header valueHeader = response.getFirstHeader(value);
							respMap.put(key, new String[]{valueHeader.getValue()});
						}
						
					}else if(Cons.RESP_CONTEXT_CONTENT.equals(context)){
						String beginString = resqElement.attributeValue("begin");
						String endString = resqElement.attributeValue("end");
						String[] strArry = StringUtils.substringsBetween(respString, beginString, endString);
						respMap.put(key, strArry);
					}
				}
			}
		}
		log.info(respString);
		return respString;
	}
	/**
	 * 检查网站是否登录成功.
	 * @param content
	 * @return
	 */
	private void isLoginSuccess(String content){
		List<Node> includeNodes = webElement.selectNodes("checkIsSuccess/includes/include");
		System.out.println(webElement.asXML());
		boolean flag = true;
		if(null != includeNodes){
			for (Node includeNode : includeNodes) {
				Element includeElement = (Element)includeNode;
				String includeString = includeElement.attributeValue("includeString");
				if(StringUtils.isNotBlank(includeString)){
					flag = flag&&content.contains(includeString);
				}
			}
			isLoginSuccess = flag;
			if(flag){
				log.info("恭喜.网站" + webName + "登录成功!!!");
			}else{
				log.info("网站" + webName + "登录失败!!!");
			}
		}else{
			log.info("网站" + webName + "没有checkIsSuccess标签.无法检查是否登录成功.默认为成功.");
			isLoginSuccess = true;
		}
	}
	/**
	 * 获取用户名.
	 * @return
	 */
	private String getUserName(){
		if(null == keyMap || keyMap.size() <= 0){
			return null;
		}
		String userName = null;
		if(keyNum >= keyMap.size()){
			keyNum = 0;
		}
		int i = 0;
		for (String name : keyMap.keySet()) {
			if(i==keyNum){
				userName =  name;
				break;
			}
			i++;
		}
		keyNum++;
		return userName;
	}

	public String getWebName() {
		return webName;
	}

	public void setWebName(String webName) {
		this.webName = webName;
	}

	public HttpClient getHttpClient() {
		return httpClient;
	}

	public void setHttpClient(HttpClient httpClient) {
		this.httpClient = httpClient;
	}
	public boolean isLoginSuccess() {
		return isLoginSuccess;
	}
	public boolean isSkip() {
		return isSkip;
	}
}
